package chapter6;

import java.util.Scanner;

/****************************************************************
 * Author：icynlau
 * Description: 检验信用卡合法性  书中给的部分方法不想用
 * Date:2021/4/6
 * ***************************************************************
 */
public class exc6_31 {
	
	public static void main(String[] args) {
		
		Scanner input=new Scanner(System.in);
		
		System.out.print("Enter a credit card number as a long integer:");
		long number=input.nextLong();
		System.out.print(number+" is "+(isValid(number)==true?"valid":"invalid"));
		
		
//		System.out.print(    isValid(4388576018402626L)  );
		
		
	}
	
	public static boolean isValid(long number) {
		
		boolean ret=false;
		
		if(getSize(number)>=13 &&getSize(number)<=16) {
			//长度匹配
			if(prefixMatched(number,4) ||prefixMatched(number,5) ||prefixMatched(number,37) ||prefixMatched(number,6) ) {
				//前缀匹配
				
				if((sumOfOddPlace(number)+sumOfDoubleEvenPlace(number)) %10==0) {
					ret=true;
					
				}else {
					System.out.print("Luhn检测结果为此卡号不合法\n");
				}
				
				
				
			}else {
				System.out.print("前缀不合法\n");
			}
			
		}else {
			System.out.print("长度不合法\n");
		}
		
		return ret;
		
	}
	
	
	/*Get the result of Step2*/
	public static int sumOfDoubleEvenPlace(long number) {
		
		
		int sum=0;
		
		
		//当卡号为14 16位时，最后一位为第13 15位（奇数位）
		//卡号为13 15位时，最后一位不是odd位
		boolean flag=true;
		if(getSize(number)==13 || getSize(number)==15) {
			flag=true;		//标志此位是否位偶数位
		}else {
			flag=false;		
		}
		
		while(number>0) {
			
			if(flag) {
				long tmp=(number%10)*2; 
				if(getSize(tmp)==1) {
					sum+=tmp;
				}else {
					sum+=tmp%10+tmp/10;
				}
				
				
				number/=10;
				flag=false;
			}else {
				number/=10;
				flag=true;
			}
			
		}
		
		return sum;
		
		
	}
	
	public static int sumOfOddPlace(long number) {
		
		int sum=0;
		
		
		//当卡号为14 16位时，最后一位为第13 15位（奇数位）
		//卡号为13 15位时，最后一位不是odd位
		boolean flag=true;
		if(getSize(number)==13 || getSize(number)==15) {
			flag=false;		//标志此位是否位奇数odd位
		}else {
			flag=true;		
		}
		
		while(number>0) {
			
			if(flag) {
				sum+=(number%10);
				number/=10;
				flag=false;
			}else {
				number/=10;
				flag=true;
			}
			
		}
		
		return sum;
		
	}
	
	public static int getSize(long d) {
		
		int size=0;
		while(d>0) {
			d/=10;
			size++;
		}
		
		return size;
	}
	
	public static boolean prefixMatched(long number, int d) {
		
		boolean ret=false;
		
		//d是否是number前缀
		
		int lenOfd=getSize(d);
		if(lenOfd==1) {
			
			while(number>10) {
				number/=10;
			}
			
			if(d==number) {
				ret=true;
			}
			
		}else {
			
			while(number>100) {
				number/=10;
			}
			
			if(number%10==d%10 &&number/10==d/10) {
				ret=true;
			}
			
		}
		
		
		return ret;
		
		
	}

}
